package ratelimit

import (
	"context"
	"errors"
	"gitee.com/yimtune/webook/internal/service/sms"
	"gitee.com/yimtune/webook/pkg/limiter"
)

// 发送短信客户端限流

var errLimited = errors.New("触发限流")

var _ sms.Service = &RateLimitSMSService{}

// 基于接口的装饰器模式

type RateLimitSMSService struct {
	// 非组合的写法
	// 可以有效阻止用户绕开装饰器
	// 必须实现 Service 的全部方法
	svc     sms.Service     // 被装饰者  接口
	limiter limiter.Limiter // 接口
	key     string
}

type RateLimitSMSServiceV1 struct {
	// 组合的写法
	// 用户可以直接访问 Service 绕开装饰器本身
	// 可以只实现Service 的部分方法
	sms.Service // 组合接口
	limiter     limiter.Limiter
	key         string
}

func (r *RateLimitSMSService) Send(ctx context.Context, tplId string, args []string, numbers ...string) error {
	// 先判断是否被限流
	limited, err := r.limiter.Limit(ctx, r.key)
	if err != nil {
		return err
	}
	if limited {
		return errLimited
	}
	// 没被限流 直接调用原方法发送短信
	return r.svc.Send(ctx, tplId, args, numbers...)
}

func NewRateLimitSMSService(svc sms.Service, l limiter.Limiter) *RateLimitSMSService {
	// 构造一个支持限流的短信服务
	return &RateLimitSMSService{
		svc:     svc,
		limiter: l,
		key:     "sms-limiter",
	}
}
